#pragma once

#include "IInstructionSet.h"
#include "R09RegisterSet.h"
#include "RAM.h"
#include "CallStack.h"

namespace VirtualHardware
{
	public ref class R09InstructionSet abstract : IInstructionSet
	{
	public:
		property IRegisterSet^ RegisterSet
		{
			virtual IRegisterSet^ get ()
			{
				return registers;
			}
		}

		R09InstructionSet(void);

	protected:
		R09RegisterSet^ registers;
		RAM^ ram;
		CallStack^ callStack;

		inline void Add();
		inline void Addl();
		inline void Sub();
		inline void Subl();
		inline void Mul();
		inline void Div();
		inline void Lddw();
		inline void Ldw();
		inline void Ldb();
		inline void Ldl();
		inline void Stdw();
		inline void Stb();
		inline void Mfh();
		inline void Mfl();
		inline void And();
		inline void Andl();
		inline void Or();
		inline void Orl();
		inline void Xor();
		inline void Nor();
		inline void Not();
		inline void Slt();
		inline void Sltl();
		inline void Sl();
		inline void Sr();
		inline void Beq();
		inline void Bne();
		inline void Bgt();
		inline void Blt();
		inline void Bge();
		inline void Ble();
		inline void Branch();
		inline void Jmp();
		inline void Jmpr();
		inline void Jal();
		inline void Jalr();
		inline void Ret();
		inline void Mov();
		inline void Clr();
		inline void Push();
		inline void Pop();
	};
}

#define PC registers[0]
#define MAR registers[1]
#define MDR registers[2]
#define IR registers[3]
#define SP registers[4]
#define RA registers[5]
#define FP registers[6]
#define HI registers[7]
#define LO registers[8]
#define F registers[9]
#define AG registers[10]
#define BG registers[11]
#define CG registers[12]
#define DG registers[13]
#define Z registers[14]
#define O registers[15]

#define OPCODE  IR >> 26
#define SAVEREG (IR << 6)  >> 28
#define REG1    (IR << 10) >> 28
#define REG2    (IR << 14) >> 28
#define LITERAL (IR << 14) >> 14
#define ADDRESS (IR << 6)  >> 6

#define ADD Add();
#define ADDL Addl();
#define SUB Sub();
#define SUBL Subl();
#define MUL Mul();
#define DIV Div();
#define LDDW Lddw();
#define LDW Ldw();
#define LDB Ldb();
#define LDL Ldl();
#define STDW Stdw();
#define STB Stb();
#define MFH Mfh();
#define MFL Mfl();
#define AND And();
#define ANDL Andl();
#define OR Or();
#define ORL Orl();
#define XOR Xor();
#define NOR Nor();
#define NOT Not();
#define SLT Slt();
#define SLTL Sltl();
#define SL Sl();
#define SR Sr();
#define BEQ Beq();
#define BNE Bne();
#define BGT Bgt();
#define BLT Blt();
#define BGE Bge();
#define BLE Ble();
#define JMP Jmp();
#define JMPR Jmpr();
#define JAL Jal();
#define JALR Jalr();
#define RET Ret();
#define MOV Mov();
#define CLR Clr();
#define PUSH Push();
#define POP Pop();
